home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / QuickDraw / TubeTest / TubeTest.p < prev    next >
Encoding:
Text File  |  1994-11-18  |  13.6 KB  |  407 lines  |  [TEXT/MPS ]

  1. {------------------------------------------------------------------------------
  2. #
  3. #    Macintosh Developer Technical Support
  4. #
  5. #    Simple Color QuickDraw Animation Sample Application
  6. #
  7. #    TubeTest
  8. #
  9. #    TubeTest.p    -    Pascal Source
  10. #
  11. #    Copyright © 1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.00                8/88
  15. #                1.01                6/92
  16. #
  17. #    Components:    TubeTest.p            August 1, 1988
  18. #                TubeTest.c            August 1, 1988
  19. #                TubeTest.r            August 1, 1988
  20. #                PTubeTest.make        August 1, 1988
  21. #                CTubeTest.make        August 1, 1988
  22. #                TCTubeTest.π        June 4, 1992
  23. #                TCTubeTest.π.rsrc    June 4, 1992
  24. #
  25. #    The TubeTest program is a simple demonstration of how to use the Palette 
  26. #    Manager in a color program.  It has a special color palette that is associated
  27. #    with the main window.  The colors are animated using the Palette Manager 
  28. #    to give a flowing tube effect.  The program is very simple, and the Palette
  29. #    Manager and drawing parts are put in separate subroutines to make it easier
  30. #    to figure out what is happening.
  31. #    
  32. #    The program is still a complete Macintosh application with a Main Event Loop,
  33. #    so there is the extra code to run the MEL.  
  34. #    
  35. #    There is a resource file that is necessary as well, to define the Menus, Window,
  36. #    Dialog, and Palette resources used in the program.  
  37. #
  38. #    See Sample and TESample for the general structure and MultiFinder techniques that
  39. #    we recommend that you use when building a new application.
  40. #
  41. ------------------------------------------------------------------------------}
  42.  
  43. PROGRAM TubeTest;
  44.  (*
  45.     File TubeTest.p
  46.  
  47.     Version 1.0: 6/2/88
  48.     
  49.     4/19/88:
  50.     TubeTest -- A small sample application written by Bo3b Johnson.
  51.     The idea is to draw two circles in varying colors in the window, then
  52.     animate the colors when the menu is chosen.    This is a complete program
  53.     with event loop and everything.    It is intended to be a simple example of
  54.     how to use the Palette Manager to do some minor color animation, and
  55.     how to use the PM to set up the colors desired in a window.
  56.     
  57.     Also see the resource file that goes with this to see how the Palette 
  58.     itself is layed out.
  59.     
  60.     Could be built with something like this:
  61.         rez TubeTest.r -o TubeTest
  62.         pascal TubeTest.p
  63.         Link TubeTest.p.o ∂
  64.             "{MPW}Libraries:"Interface.o ∂
  65.             "{MPW}Libraries:"Runtime.o ∂
  66.             "{MPW}PLibraries:"Paslib.o ∂
  67.             -o TubeTest
  68.         TubeTest
  69.  *)
  70.  
  71.  {Where does it fit:
  72.     This is a series of sample programs for those doing development
  73.     using Color QuickDraw.  Since the whole color problem depends
  74.     upon the exact effect desired, there are a number of answers
  75.     to how to use colors, from the simple to the radically complex.
  76.     These programs try to cover the gamut, so you should use 
  77.     which ever seems appropriate.  In most cases, use the simplest
  78.     one that will give the desired results.  The compatibility
  79.     rating is from 0..9 where low is better.  The more known risks 
  80.     there are the higher the rating.
  81.     
  82.     
  83.     The programs (in order of compatibility):
  84.     
  85.         SillyBalls:
  86.             This is the simplest use of Color QuickDraw, and does
  87.             not use the Palette Manager.  It draws randomly colored
  88.             balls in a color window.  This is intended to give you
  89.             the absolute minimum required to get color on the screen.
  90.             Written in straight Pascal code.
  91.             Compatibility rating = 0, no known risks.
  92.         
  93.         FracAppPalette:
  94.             This is a version of FracApp that uses only the Palette
  95.             Manager.  It does not support color table animation
  96.             since that part of the Palette Manager is not sufficient.
  97.             The program demonstrates a full color palette that is
  98.             used to display the Mandelbrot set.  It uses an offscreen
  99.             gDevice w/ Port to handle the data, using CopyBits to
  100.             draw to the window.  The Palette is automatically 
  101.             associated with each window.  The PICT files are read
  102.             and written using the bottlenecks, to save on memory
  103.             useage.
  104.             Written in MacApp Object Pascal code.
  105.             Compatibility rating = 0, no known risks.
  106.         
  107.         TubeTest:    (***)
  108.             This is a small demo program that demonstrates using the
  109.             Palette Manager for color table animation.  It uses a 
  110.             color palette with animating entries, and draws using the
  111.             Palette Manager.  There are two circles of animating colors
  112.             which gives a flowing tube effect.  This is a valid case
  113.             for using the animating colors aspect of the Palette Manager,
  114.             since the image is being drawn directly.
  115.             Written in straight Pascal code.
  116.             Compatibility rating = 0, no known risks.
  117.         
  118.         FracApp:
  119.             This is the ‘commercial quality’ version of FracApp.  This
  120.             version supports color table animation, using an offscreen
  121.             gDevice w/ Port, and handles multiple documents.  The
  122.             CopyBits updates to the screen are as fast as possible.  The
  123.             program does not use the Palette Manager, except to
  124.             provide for the system palette, or color modes with less than
  125.             255 colors.  For color table animation using an offscreen
  126.             gDevice w/ Port, it uses the Color Manager and handles the
  127.             colors itself.  Strict compatibility was relaxed to allow for
  128.             a higher performance program.  This is the most ‘real’ of the
  129.             sample programs.
  130.             Written in MacApp Object Pascal code.
  131.             Compatibility rating = 2.  (nothing will break, but it may not
  132.             always look correct.)
  133.         
  134.         FracApp300:
  135.             This doesn't support colors, but demonstrates how to create and
  136.             use a 300 dpi bitmap w/ Port.  The bitmap is printed at full
  137.             resolution on LaserWriters, and clipped on other printers (but
  138.             they still print).  It demonstrates how to use a high resolution
  139.             image as a PICT file, and how to print them out.
  140.             Written in MacApp Object Pascal code.
  141.             Compatibility rating = 1.  (The use of PrGeneral is slightly 
  142.             out of the ordinary, although supported.)
  143. }
  144.  
  145.  {$R-}    { No range checking.}
  146.  {$D+}    { Debugging labels on. }
  147.  
  148.  
  149.     { Interface files with all the happy Macintosh stuff in them. }
  150. USES 
  151.     Types, QuickDraw, Events, Controls, Windows, TextEdit, Dialogs, Fonts, Lists, Menus,
  152.     Resources, Scrap, ToolUtils, 
  153.     OSUtils, Files, Devices, DeskBus, DiskInit, Disks, Errors, Memory, Retrace, SegLoad, Serial,
  154.     ShutDown, Slots, Sound, Start, Timer, Palettes;
  155.     
  156.     
  157. CONST
  158.     appleID                    = 1000;        { resource IDs/menu IDs for Apple, File and Edit menus }
  159.     fileID                    = 1001;
  160.     editID                    = 1002;
  161.     
  162.     appleM                    = 1;        { Index for each menu in myMenus (array of menu handles) }
  163.     fileM                    = 2;
  164.     editM                    = 3;
  165.  
  166.     menuCount                = 3;        { Total number of menus }
  167.  
  168.     windowID                = 1000;        { Resource ID for main window }
  169.     aboutMeDLOG             = 1000;        { And Resource ID for About box dialog. }
  170.  
  171.     tubularItem                = 1;        { When checked, animation of colors. }
  172.     quitItem                = 3;        { Quit in the menu of course. }
  173.  
  174.     aboutMeCommand            = 1;        { Menu item in apple menu for About TubeTest item }
  175.     
  176.     totalColors                = 152;        { use 150 colors in our palette for drawing eyes. }
  177.     numColors                = 150;        { to skip black and white. }
  178.     
  179.     
  180.  
  181. VAR
  182.     myMenus:        ARRAY [1..menuCount] OF MenuHandle;
  183.     dragRect:        Rect;                { Rectangle used to mark bounds for dragging window }
  184.     doneFlag:        BOOLEAN;            { TRUE if user has chosen Quit command }
  185.     myEvent:        EventRecord;
  186.     myWindow:        WindowPtr;
  187.     whichWindow:    WindowPtr;
  188.     tubeCheck:        Boolean;            { if true, the menu is checked, and we animate. }
  189.     theChar:        Char;
  190.     error:             OSErr;
  191.     theWorld:         SysEnvRec;
  192.     
  193.     { This routine will update the window when required by update events.    It
  194.         will draw two circular dudes that are indexed in colors through the colors
  195.         we are using. 0 and 1 are skipped, since those are white and black in the
  196.         palette. }
  197. PROCEDURE DrawEyes;
  198.     
  199.     VAR        TempRect:    Rect;
  200.             I:            Integer;
  201.     
  202. BEGIN
  203.     SetRect(TempRect, numColors, numColors, numColors, numColors);
  204.     For I := 2 To totalColors Do Begin
  205.         PmForeColor(I);
  206.         FrameOval (TempRect);
  207.         InsetRect (TempRect, -1, -1);
  208.     END;
  209.     
  210.     SetRect(TempRect, numColors*3, numColors, numColors*3, numColors);
  211.     For I := totalColors DownTo 2 Do Begin
  212.         PmForeColor(I);
  213.         FrameOval (TempRect);
  214.         InsetRect (TempRect, -1, -1);
  215.     END;
  216. END;    { DrawEyes }
  217.  
  218.  
  219. PROCEDURE SetUpMenus;
  220.  
  221.     VAR        I:    INTEGER;
  222.  
  223. BEGIN
  224.     { Read menu descriptions from resource file into memory and store handles
  225.     in myMenus array }
  226.     myMenus[appleM] := GetMenu(appleID);    {read Apple menu from resource file}
  227.     AppendResMenu(myMenus[appleM], 'DRVR');    {add desk accessory names to Apple menu}
  228.     myMenus[fileM] := GetMenu(fileID);        {read file menu from resource file}
  229.     myMenus[editM] := GetMenu(editID);        {read edit menu from resource file}
  230.  
  231.     FOR I := 1 TO menuCount DO InsertMenu(myMenus[I], 0); {install menus in menu bar}
  232.     
  233.     DrawMenuBar;                            {and draw menu bar}
  234. END; { SetUpMenus }
  235.  
  236.  
  237.     { Use the Palette currently attached to the main window to animate the colors 
  238.     in the circular eye shapes.  This will rotate them around to give the flowing 
  239.     tube effect. We make the palette into a color table so we can move entries 
  240.     around.    We have to skip the first two entries since those are black and white. 
  241.     (entries 0 and 1) }
  242. PROCEDURE ShiftyColors;
  243.     
  244.     VAR        currPalette:    PaletteHandle;
  245.             destCTab:        CTabHandle;
  246.             lastCSpec:        ColorSpec;
  247.     
  248. BEGIN
  249.     SetPort (myWindow);
  250.     
  251.     currPalette := GetPalette(myWindow);
  252.     destCTab := CTabHandle (NewHandle (SIZEOF (ColorTable)+(totalColors*SIZEOF(ColorSpec))));
  253.     IF destCTab = NIL  THEN Exit (ShiftyColors);
  254.     Palette2CTab(currPalette, destCTab);
  255.     
  256.         { Move the colors around in the color table, skipping 0 and 1, and moving
  257.         all the elements down by one, and copying the element at 2 back to the 
  258.         end of the table. The effect is to rotate the colors in the table.    }
  259.     lastCSpec := destCTab^^.ctTable[2];                            { pull first one off. }
  260.     BlockMove (@destCTab^^.ctTable[3], @destCTab^^.ctTable[2], 
  261.                 (numColors) * SIZEOF (ColorSpec) );                { copy all one entry down. }
  262.     destCTab^^.ctTable[totalColors-1] := lastCSpec;                { put last color back on front. }
  263.         
  264.     AnimatePalette(myWindow, destCTab, 2, 2, numColors);
  265.     
  266.     DisposeHandle (Handle (destCTab));
  267. END;    { ShiftyColors }
  268.  
  269.  
  270.     { Display the dialog box in response to the 'About TubeTest' menu item. }
  271. PROCEDURE ShowAboutMeDialog;
  272.  
  273.     VAR        theDialog:    DialogPtr;
  274.             itemHit:    Integer;
  275.  
  276. BEGIN
  277.     theDialog := GetNewDialog(aboutMeDLOG, NIL, WindowPtr( - 1));
  278.     ModalDialog(NIL, itemHit);
  279.     DisposeDialog(theDialog);
  280. END; { ShowAboutMeDialog }
  281.  
  282.  
  283.     { Execute menu command specified by mResult, the result of MenuSelect }
  284. PROCEDURE DoCommand(mResult: LONGINT);
  285.  
  286.     VAR        theItem:    INTEGER;                { menu item number from mResult low-order word }
  287.             theMenu:    INTEGER;                { menu number from mResult high-order word }
  288.             name:         Str255;                    { desk accessory name }
  289.             temp:         INTEGER;
  290.             dummy:        Boolean;
  291.  
  292. BEGIN
  293.     theItem := LoWord(mResult);                    { call Toolbox Utility routines to }
  294.     theMenu := HiWord(mResult);                    { set menu item number and menu }
  295.  
  296.     CASE theMenu OF                                { case on menu ID }
  297.  
  298.         appleID:
  299.             IF (theItem = aboutMeCommand) THEN  ShowAboutMeDialog
  300.             ELSE
  301.                 BEGIN                            { call Menu Manager to get desk acc.}
  302.                     GetMenuItemText(myMenus[appleM], theItem, name);
  303.                     temp := OpenDeskAcc(name);
  304.                     SetPort(myWindow);
  305.                 END; { appleID }
  306.  
  307.         fileID:
  308.             BEGIN
  309.                 IF theItem = quitItem THEN doneFlag := TRUE;
  310.                 
  311.                 IF theItem = tubularItem THEN BEGIN
  312.                     tubeCheck := NOT tubeCheck;
  313.                     CheckItem(myMenus[fileM], tubularItem, tubeCheck);
  314.                 END;
  315.             END;    { fileID }
  316.  
  317.         editID:
  318.                 dummy := SystemEdit(theItem - 1);{ Pass the command on to the Desk Manager.}
  319.  
  320.     END; {of menu CASE}
  321.  
  322.     HiliteMenu(0);                        { Unhighlight menu title(highlighted by MenuSelect) }
  323. END; {of DoCommand}
  324.  
  325.  
  326. BEGIN  { Main }
  327.     { Test the computer to be sure we can do color.  If not we would crash, which
  328.     would be bad.  If we can’t run, just beep and exit. }
  329.     error := SysEnvirons(1, theWorld);
  330.     IF NOT theWorld.hasColorQD THEN BEGIN
  331.         SysBeep (50);
  332.         ExitToShell;                { If no color QD, we must leave. }
  333.     END;
  334.  
  335.     InitGraf(@qd.thePort);
  336.     InitFonts;
  337.     InitWindows;
  338.     InitMenus;
  339.     TEInit;
  340.     InitDialogs(NIL);
  341.     InitCursor;
  342.  
  343.     WITH qd.screenBits.bounds DO
  344.         SetRect(dragRect, 4, 24, right - 4, bottom - 4);
  345.     doneFlag := FALSE;                { flag to detect when Quit command is chosen}
  346.     tubeCheck := FALSE;                { flag for animating color is initially off. }
  347.  
  348.         { Open the color window. }
  349.     myWindow := GetNewCWindow(windowID, NIL, POINTER(-1));
  350.     SetPort(myWindow);
  351.  
  352.         { Set up menus last, since the menu drawing can then use the palette we have for ou
  353.         window. Makes the Apple look better, in particular. }
  354.     SetUpMenus;
  355.     
  356.     { Main Event Loop }
  357.     REPEAT
  358.         SystemTask;
  359.  
  360.         IF GetNextEvent(everyEvent, myEvent) THEN
  361.             CASE myEvent.what OF            { case on event type}
  362.  
  363.                 mouseDown:
  364.                     CASE FindWindow(myEvent.where, whichWindow) OF
  365.  
  366.                         inSysWindow:                { desk accessory window: call Desk Manager to handle it}
  367.                                 SystemClick(myEvent, whichWindow);
  368.  
  369.                         inMenuBar:                    { Menu bar: learn which command, then execute it. }
  370.                                 DoCommand(MenuSelect(myEvent.where));
  371.  
  372.                         inDrag:                        { title bar: call Window Manager to drag}
  373.                                 DragWindow(whichWindow, myEvent.where, dragRect);
  374.  
  375.                         inContent:                    { body of application window: }
  376.                                 IF whichWindow <> frontWindow THEN
  377.                                     SelectWindow(whichWindow); {and make it active if not}
  378.                     END; {of mouseDown}
  379.  
  380.                 updateEvt:                            { Update the eyes in window. }
  381.                     IF WindowPtr(myEvent.message) = myWindow THEN
  382.                         BEGIN
  383.                             BeginUpdate(WindowPtr(myEvent.message));
  384.                                 DrawEyes;
  385.                             EndUpdate(WindowPtr(myEvent.message));
  386.                         END; {of updateEvt}
  387.                             
  388.                 keyDown, autoKey:                    { key pressed once or held down to repeat }
  389.                     IF myWindow = frontWindow THEN
  390.                         BEGIN
  391.                             theChar := CHR(BAnd(myEvent.message, charCodeMask)); { get the char }
  392.                                 { If Command key down, do it as a Menu Command. }
  393.                             IF BAnd(myEvent.modifiers, cmdKey) <> 0 THEN DoCommand(MenuKey(theChar));
  394.                         END; {of keyDown and autoKey}
  395.  
  396.             END; {of event CASE}
  397.  
  398.             { If we have menu item checked, go ahead and animate colors. }
  399.         IF tubeCheck THEN ShiftyColors;
  400.         
  401.     UNTIL doneFlag;
  402.  
  403.         { clean up after palette manager, so he can chuck the palette in use. }
  404.     DisposeWindow (myWindow);
  405.     
  406. END.
  407.